package com.shaoshaohuo.app.net;

import android.content.Context;
import android.util.Log;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request.Priority;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.RequestParams;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;
import com.shaoshaohuo.app.SshApplication;
import com.shaoshaohuo.app.entity.BaseEntity;
import com.shaoshaohuo.app.framework.AccountManager;
import com.shaoshaohuo.app.framework.Logger;
import com.shaoshaohuo.app.framework.Logger.LogTag;
import com.shaoshaohuo.app.framework.log.LogUtil;
import com.shaoshaohuo.app.utils.DeviceHelper;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;

/**
 * 真正请求
 * @ClassName: NetRequestManager
 * @Description: 网络请求
 * @author Ysl
 */
public class HttpRequest {

    private Context context;

    public HttpRequest(Context context) {
        this.context = context;
    }

    //Add from V1.8.1.2, resolve mthread_create out of memory problem.
    public static RequestQueue requestQueue = Volley.newRequestQueue(SshApplication.getContext());

    public <T> void get(int requestCode, Map<String, String> map, String subUrl, final Class<? extends BaseEntity> clazz,
                    final RequestListener callback) {
        if (!DeviceHelper.isNetworkConnected(SshApplication.getContext())) {
            callback.onFailed(requestCode, new Exception(), "无网络连接");
            return;
        }
        String url = HttpConfig.getRequestUrl(subUrl);
        if (map != null && !map.isEmpty()) {
            checkNull(map);
            url = url + encodeParameters(map);
        }
        get(requestCode, url, clazz, callback, Priority.NORMAL, new DefaultRetryPolicy(10 * 1000, 0, 1));
    }
    /**
     * get 请求 添加到队列方法
     * @param requestCode
     * @param url
     * @param clazz
     * @param callback
     * @param priority
     * @param retryPolicy
     */
    private <T> void get(final int requestCode, final String url, final Class<? extends BaseEntity> clazz, final RequestListener callback,
                    final Priority priority, RetryPolicy retryPolicy) {
        StringGetRequest req = new StringGetRequest(url, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                try {
                    LogUtil.d(LogTag.HTTP+".get", url);
                    LogUtil.d(LogTag.HTTP+".get.response", response);
                    BaseEntity result = new Gson().fromJson(response, clazz);
                    if (result == null) {
                        callback.onFailed(requestCode, new NullPointerException(), "Data:" + response);
                        return;
                    }
                    if (result.isAuthTokenInvalid()) {
                        AccountManager.authExpiredAndLogin(context);
                    }
                    callback.onSuccess(requestCode, result);
                } catch (Exception e) {
                    callback.onFailed(requestCode, e, e.getClass().toString());
                }
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                LogUtil.d(LogTag.HTTP+".get", url);
                LogUtil.e(LogTag.HTTP+".get.error", Log.getStackTraceString(error));
                callback.onFailed(requestCode, error, error.getMessage());
            }
        }) {

            @Override
            public Priority getPriority() {
                if (priority == Priority.LOW) {
                    return Priority.LOW;
                } else if (priority == Priority.NORMAL) {
                    return Priority.NORMAL;
                } else if (priority == Priority.IMMEDIATE) {
                    return Priority.IMMEDIATE;
                } else if (priority == Priority.HIGH) {
                    return Priority.HIGH;
                }
                return Priority.NORMAL;
            }
        };
        if (retryPolicy != null) {
            req.setRetryPolicy(retryPolicy);
        }
//        Volley.newRequestQueue(context).add(req);
        requestQueue.add(req);
    }

    public <T> void post(int requestCode, Map<String, String> map, String subUrl, final Class<? extends BaseEntity> clazz,
                    final RequestListener callback) {
        if (!DeviceHelper.isNetworkConnected(SshApplication.getContext())) {
            callback.onFailed(requestCode, new Exception(), "无网络连接");
            return;
        }
        String url = HttpConfig.getRequestUrl(subUrl);
        post(requestCode, url, clazz, map, callback);
    }
    
    public <T> void post( Map<String, String> map, String subUrl, final Class<? extends BaseEntity> clazz,
                    final RequestListener callback) {
        if (!DeviceHelper.isNetworkConnected(SshApplication.getContext())) {
            callback.onFailed(0, new Exception(), "无网络连接");
            return;
        }
        String url = HttpConfig.getRequestUrl(subUrl);
        post(0, url, clazz, map, callback);
    }

    private <T> void post(int requestCode, String url, final Class<? extends BaseEntity> clazz, final Map<String, String> map,
                    final RequestListener callback) {
        post(requestCode, url, clazz, map, callback, Priority.NORMAL, new DefaultRetryPolicy(10 * 1000, 0, 1));
    }

    /**
     *  post  请求 添加到 队列方法
     * @param requestCode
     * @param url
     * @param clazz
     * @param map
     * @param callback
     * @param priority
     * @param retryPolicy
     * @param <T>
     */
    private <T> void post(final int requestCode, final String url, final Class<? extends BaseEntity> clazz, final Map<String, String> map,
                    final RequestListener callback, final Priority priority, RetryPolicy retryPolicy) {

        StringPostRequest req = new StringPostRequest(url, new Response.Listener<String>() {

            public static final String TAG = "TAG";

            @Override
            public void onResponse(String response) {
                try {
                    Log.e(TAG, "onResponse: "+url+"=====>"+response);
                    LogUtil.d(LogTag.HTTP+".post.url", url);
                    LogUtil.d(LogTag.HTTP+".post.params", "Params:" + map.toString());
                    LogUtil.d(LogTag.HTTP+".post.response", response);
                    BaseEntity result = new Gson().fromJson(response, clazz);
                    if (result == null) {
                        callback.onFailed(requestCode, new NullPointerException(), "Data:" + response);
                        return;
                    }
                    if (result.isAuthTokenInvalid()) {
                        AccountManager.authExpiredAndLogin(context);
                    }
                    callback.onSuccess(requestCode, result);
                } catch (Exception e) {
                    callback.onFailed(requestCode, e, e.getClass().toString());
                }
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                LogUtil.d(LogTag.HTTP+".post.url", url);
                LogUtil.d(LogTag.HTTP+".post.params", "Params:" + map.toString());
                LogUtil.e(LogTag.HTTP+".post.error", Log.getStackTraceString(error));
                callback.onFailed(requestCode, error, error.getMessage());
            }
        }) {

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                checkNull(map);
                return map;
            }

            @Override
            public Priority getPriority() {
                if (priority == Priority.LOW) {
                    return Priority.LOW;
                } else if (priority == Priority.NORMAL) {
                    return Priority.NORMAL;
                } else if (priority == Priority.IMMEDIATE) {
                    return Priority.IMMEDIATE;
                } else if (priority == Priority.HIGH) {
                    return Priority.HIGH;
                }
                return Priority.NORMAL;
            }
        };
        if (retryPolicy != null) {
            req.setRetryPolicy(retryPolicy);
        }
        req.setTag(context);
//        Volley.newRequestQueue(context).add(req); //Here will cause out of memory by a lot of hit
        requestQueue.add(req);
    }
    /**
     *  上传图片
     * @param mediatype
     * @param isSupply 标识是否添加水印
     * @param requestCode
     * @param url
     * @param filePath
     * @param clazz
     * @param callBack
     */
    public <T> void uploadImage(String mediatype, String isSupply, final int requestCode, String url, String filePath, final Class<? extends BaseEntity> clazz,
                    final RequestListener callBack) {

        if (!DeviceHelper.isNetworkConnected(SshApplication.getContext())) {
            callBack.onFailed(requestCode, new Exception(), "无网络连接");
            return;
        }
        url = HttpConfig.getRequestUrl(url);

        RequestParams params = new RequestParams();
        LogUtil.e(LogTag.HTTP + ".uploadImage", "uploadPath:" + filePath + "\r\n" + "url:" + url+"--mediatype:"+mediatype);
        RequestParam.setHeaderParams(params);
        params.addBodyParameter("file", new File(filePath));
        params.addBodyParameter("mediatype", mediatype);
        params.addBodyParameter("isSupply", isSupply);
        HttpUtils http = new HttpUtils();
        http.send(HttpMethod.POST, url, params, new RequestCallBack<String>() {

            @Override
            public void onStart() {
                LogUtil.d(LogTag.HTTP+ ".upload", "upload  onStart");
            }

            @Override
            public void onLoading(long total, long current, boolean isUploading) {
                LogUtil.d(LogTag.HTTP+".uploading", "total:" + total + "--current:" + current + "--isUploading:" + isUploading);
            }

            @Override
            public void onSuccess(ResponseInfo<String> responseInfo) {
//                LogUtil.d(LogTag.HTTP, "total:" + responseInfo.result);
                String response = responseInfo.result;
                try {
                    LogUtil.d(LogTag.HTTP+".upload.response", response);
                    BaseEntity result = new Gson().fromJson(response, clazz);
                    if (result == null) {
                        callBack.onFailed(requestCode, new NullPointerException(), "Data:" + response);
                        return;
                    }
                    if (result.isAuthTokenInvalid()) {
                        AccountManager.authExpiredAndLogin(context);
                    }
                    callBack.onSuccess(requestCode, result);
                } catch (Exception e) {
                    callBack.onFailed(requestCode, e, e.getClass().toString());
                }
            }

            @Override
            public void onFailure(HttpException error, String msg) {
                LogUtil.e(LogTag.HTTP + ".upload.error", "error:" + Log.getStackTraceString(error) + "--msg:" + msg);
                callBack.onFailed(requestCode, error, msg);
            }
        });
    }/**
     * HttpUtil
     * @param mediatype
     * @param requestCode
     * @param url
     * @param filePath
     * @param clazz
     * @param callBack
     */
    public <T> void uploadImage(String mediatype, final int requestCode, String url, String filePath, final Class<? extends BaseEntity> clazz,
                    final RequestListener callBack) {

        if (!DeviceHelper.isNetworkConnected(SshApplication.getContext())) {
            callBack.onFailed(requestCode, new Exception(), "无网络连接");
            return;
        }
        url = HttpConfig.getRequestUrl(url);

        RequestParams params = new RequestParams();
        Logger.e(LogTag.HTTP, "uploadPath:" + filePath + "\r\n" + "url:" + url+"--mediatype:"+mediatype);
        RequestParam.setHeaderParams(params);
        params.addBodyParameter("file", new File(filePath));
        params.addBodyParameter("mediatype", mediatype);
        HttpUtils http = new HttpUtils();
        http.send(HttpMethod.POST, url, params, new RequestCallBack<String>() {

            @Override
            public void onStart() {
//                Logger.d(LogTag.HTTP, "upload  onStart");
            }

            @Override
            public void onLoading(long total, long current, boolean isUploading) {
//                Logger.d(LogTag.HTTP, "total:" + total + "--current:" + current + "--isUploading:" + isUploading);
            }

            @Override
            public void onSuccess(ResponseInfo<String> responseInfo) {
                Logger.d(LogTag.HTTP, "total:" + responseInfo.result);
                String response = responseInfo.result;
                try {
                    Logger.d(LogTag.HTTP, response);
                    BaseEntity result = new Gson().fromJson(response, clazz);
                    if (result == null) {
                        callBack.onFailed(requestCode, new NullPointerException(), "Data:" + response);
                        return;
                    }
                    if (result.isAuthTokenInvalid()) {
                        AccountManager.authExpiredAndLogin(context);
                    }
                    callBack.onSuccess(requestCode, result);
                } catch (Exception e) {
                    callBack.onFailed(requestCode, e, e.getClass().toString());
                }
            }

            @Override
            public void onFailure(HttpException error, String msg) {
                Logger.e(LogTag.HTTP, "error:" + Log.getStackTraceString(error) + "--msg:" + msg);
                callBack.onFailed(requestCode, error, msg);
            }
        });
    }
    /**
     * 检查map key 清空 null
     * @param map
     * @return
     */
    private static Map<String, String> checkNull(Map<String, String> map) {
        if (map != null && map.size() >= 0) {
            Set<String> set = map.keySet();
            LinkedList<String> list = new LinkedList<String>();
            for (Iterator<String> iterator = set.iterator(); iterator.hasNext();) {
                String key = (String) iterator.next();
                String value = map.get(key);
                if (value == null || value.equals("null")) {
                    list.add(key);
                }
            }
            for (String key : list) {
                map.remove(key);
            }
        }
        return map;
    }
    /**
     *  生成 get参数  url 编码
     * @param params
     * @return
     */
    private static String encodeParameters(Map<String, String> params) {
        StringBuilder encodedParams = new StringBuilder("?");
        try {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                encodedParams.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                encodedParams.append('=');
                encodedParams.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
                encodedParams.append('&');
            }
            return encodedParams.toString();
        } catch (UnsupportedEncodingException uee) {
            throw new RuntimeException("Encoding not supported: " + "UTF-8", uee);
        }
    }
    /**
     * 	回调接口
     * @author cao
     *
     */
    public interface RequestListener {

        void onSuccess(int requestCode, BaseEntity resultData);

        void onFailed(int requestCode, Exception error, String msg);
    }
}
